<template>
  <view class="page">
    <view class="header">活动日历</view>

    <view class="calendar">
      <view class="cal-head">
        <view class="arrow" @click="prevMonth">‹</view>
        <view class="ym">{{ year }}年{{ month }}月</view>
        <view class="arrow" @click="nextMonth">›</view>
      </view>
      <view class="week">
        <text v-for="(w,i) in weeks" :key="i" class="w">{{ w }}</text>
      </view>
      <view class="grid">
        <view v-for="(d,idx) in calendarGrid" :key="idx" class="cell" :class="{ off: !d.inMonth, sel: isSelected(d) }" @click="selectDate(d)">
          <text class="num">{{ d.day }}</text>
          <view v-if="d.inMonth && hasDot(d)" class="dot"></view>
        </view>
      </view>
    </view>

    <view class="cards">
      <view class="cards-title">{{ selectedDate }} 活动/课程</view>
      <view v-if="entries.length === 0" class="empty">当日暂无活动/课程</view>
      <view v-for="(a,i) in entries" :key="i" class="card">
        <view class="title">{{ a.title }}</view>
        <view class="meta">{{ a.date }} · {{ a.place }}</view>
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { getStorage } from '../../utils/storage';

type Entry = { id: string; title: string; date: string; place: string; type?: string };
const ACT_KEY = 'ACTIVITY_PARTICIPATE';
const COURSE_KEY = 'COURSE_PARTICIPATE';

const today = new Date();
const curYear = ref(today.getFullYear());
const curMonth = ref(today.getMonth() + 1);
const selectedDate = ref(formatDate(today));

const weeks = ['日','一','二','三','四','五','六'];

const year = computed(() => curYear.value);
const month = computed(() => curMonth.value);

function formatDate(dt: Date): string {
  const y = dt.getFullYear();
  const m = String(dt.getMonth() + 1).padStart(2,'0');
  const d = String(dt.getDate()).padStart(2,'0');
  return `${y}-${m}-${d}`;
}

const daysInMonth = (y: number, m: number) => new Date(y, m, 0).getDate();
const firstDayWeek = (y: number, m: number) => new Date(y, m - 1, 1).getDay();

const calendarGrid = computed(() => {
  const y = year.value; const m = month.value;
  const dim = daysInMonth(y, m);
  const fdw = firstDayWeek(y, m);
  const prevDim = daysInMonth(m === 1 ? y - 1 : y, m === 1 ? 12 : m - 1);
  const cells: { inMonth: boolean; day: number; y: number; m: number; d: number }[] = [];
  for (let i = fdw - 1; i >= 0; i--) cells.push({ inMonth: false, day: prevDim - i, y, m, d: 0 });
  for (let d = 1; d <= dim; d++) cells.push({ inMonth: true, day: d, y, m, d });
  const rest = (7 - (cells.length % 7)) % 7;
  for (let i = 1; i <= rest; i++) cells.push({ inMonth: false, day: i, y, m, d: 0 });
  return cells;
});

const mapAct = ref<Record<string, Entry[]>>({});
const mapCourse = ref<Record<string, Entry[]>>({});
const refresh = () => {
  mapAct.value = getStorage(ACT_KEY) || {};
  mapCourse.value = getStorage(COURSE_KEY) || {};
};

const hasDot = (cell: any) => {
  if (!cell.inMonth) return false;
  const y = year.value; const m = String(month.value).padStart(2, '0');
  const d = String(cell.day).padStart(2, '0');
  const key = `${y}-${m}-${d}`;
  const a = mapAct.value[key]?.length || 0;
  const c = mapCourse.value[key]?.length || 0;
  return a + c > 0;
};

const isSelected = (cell: any) => {
  if (!cell.inMonth) return false;
  const y = year.value; const m = String(month.value).padStart(2, '0');
  const d = String(cell.day).padStart(2, '0');
  return selectedDate.value === `${y}-${m}-${d}`;
};

const entries = ref<Entry[]>([]);
const updateEntries = () => {
  const list = [ ...(mapAct.value[selectedDate.value] || []), ...(mapCourse.value[selectedDate.value] || []) ];
  entries.value = list;
};

const selectDate = (cell: any) => {
  if (!cell.inMonth) return;
  const y = year.value; const m = String(month.value).padStart(2, '0');
  const d = String(cell.day).padStart(2, '0');
  selectedDate.value = `${y}-${m}-${d}`;
  updateEntries();
};

const prevMonth = () => {
  if (curMonth.value === 1) { curMonth.value = 12; curYear.value -= 1; }
  else { curMonth.value -= 1; }
};
const nextMonth = () => {
  if (curMonth.value === 12) { curMonth.value = 1; curYear.value += 1; }
  else { curMonth.value += 1; }
};

refresh();
updateEntries();

watch([curYear, curMonth], () => {
  const y = year.value; const m = String(month.value).padStart(2, '0');
  const parts = selectedDate.value.split('-');
  if (parts[0] !== String(y) || parts[1] !== m) {
    selectedDate.value = `${y}-${m}-01`;
  }
});
</script>

<style lang="scss">
.page { min-height: 100vh; background: #314039; }
.header { padding: 24rpx; font-size: 32rpx; font-weight: 600; }
.calendar { margin: 20rpx; background: #fff; border-radius: 16rpx; padding: 16rpx; }
.cal-head { display: flex; align-items: center; justify-content: space-between; padding: 8rpx 8rpx 16rpx; }
.arrow { width: 64rpx; text-align: center; font-size: 40rpx; }
.ym { font-size: 30rpx; font-weight: 600; }
.week { display: grid; grid-template-columns: repeat(7, 1fr); padding: 8rpx 0; color: #999; font-size: 24rpx; }
.w { text-align: center; }
.grid { display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 100rpx; gap: 8rpx; }
.cell { position: relative; background: #fafafa; border-radius: 12rpx; display: flex; align-items: flex-start; justify-content: flex-end; padding: 10rpx; }
.cell.off { color: #ccc; background: #f6f6f6; }
.cell.sel { outline: 2rpx solid #a8c6df; }
.num { font-size: 26rpx; color: #333; }
.dot { position: absolute; left: 50%; bottom: 12rpx; transform: translateX(-50%); width: 12rpx; height: 12rpx; background: #ff4d4f; border-radius: 50%; }
.cards { padding: 0 20rpx 20rpx; }
.cards-title { padding: 16rpx 0; color: #666; font-size: 26rpx; }
.empty { background: #fff; border-radius: 16rpx; padding: 60rpx 0; text-align: center; color: #999; }
.card { background: #fff; border-radius: 16rpx; padding: 24rpx; margin-bottom: 16rpx; }
.title { font-size: 30rpx; font-weight: 600; color: #333; }
.meta { margin-top: 8rpx; color: #888; font-size: 26rpx; }
</style>


